package tuvienna.jade;

import jade.core.AID;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ParticipantStatus extends InterestSet {

	private static final long serialVersionUID = -1679101145816202866L;
	AID table;
	public ParticipantStatus(InterestSet copy, AID table)
	{
		for(String i: copy.keySet())
			put(i, copy.get(i));		
		this.table = table;
	}
	
	public int computeEdgeWeight(ParticipantStatus other)
	{
		int res = 0;
		for(String i: other.keySet())
			if(this.containsKey(i))
				res++;
		return res;
	}
	public AID getTable()
	{
		return table;
	}
	
	public static double computeClusteringCoefficient(Collection<ParticipantStatus> collection)
	{
		//copy the map to make sure no interrupting hijinks are going on
		List<ParticipantStatus> status = new ArrayList<ParticipantStatus>(collection);
		int cnt = status.size();
		int[][] edges = new int[cnt][];
		for(int i=0;i<cnt;i++)
		{
			edges[i] = new int[cnt];
			for(int j=0;j<cnt;j++)
				edges[i][j] = status.get(i).computeEdgeWeight(status.get(j));
		}

			double totalSum = 0;
		double clusteredSum = 0; 

		//simple edgewise accumulation
		for(int i=0;i<cnt;i++)
			for(int j=0;j<i;j++)
			{
				if(status.get(i).getTable() != null &&
				   status.get(i).getTable().equals(status.get(j).getTable()))
					clusteredSum += edges[i][j];
				totalSum += edges[i][j];
			}

		//edgewise accum per table, and averaging the result at the end
		//ignores null tables for the clustering, so the clusteringvalue is (always) higher
		/*HashMap<AID,Double> inside = new HashMap<AID,Double>();
		for(int i=0;i<cnt;i++)
			inside.put(status.get(i).getTable(), (double) 0);
		HashMap<AID,Double> total = new HashMap<AID,Double>(inside);
				
		for(int i=0;i<cnt;i++)
			for(int j=0;j<cnt;j++)
			{
				AID ti = status.get(i).getTable();
				AID tj = status.get(j).getTable();							
				if(ti!= null)
				
					if(ti.equals(tj))
						inside.put(ti, inside.get(ti) + edges[i][j]);
					total.put(ti, total.get(ti) + edges[i][j]);	
				
			}
		totalSum = total.size();
		for(AID t: inside.keySet() )
			clusteredSum += inside.get(t) / total.get(t);*/
		
		/*//TRIANGLE CLUSTERINGS
		//the awesomeo clustering technique I just invented..^^
		//for every triangle
		for(int i=0;i<cnt;i++)
			for(int j=0;j<i;j++)
				for(int k=0;k<j;k++)
				{	//compute our clustering metric (might as well be average, min or max)
					double value = Math.pow(edges[i][j] * edges[j][k] * edges[k][i],1/3.0);
					
					//All three vertices on the same table? (nulls don't join any table)
					if(status.get(i).getTable()!= null && 
				    	status.get(i).getTable().equals(status.get(j).getTable()) && 
						status.get(j).getTable().equals(status.get(k).getTable()))
						clusteredSum += value;

					totalSum +=value;
				}*/
		
		//based on http://toreopsahl.com/tnet/weighted-networks/clustering/
		//I used the above since this requires n^3 loops above ..1/6 *n*(n-1)*(n-2).. ..soo much better^^
		//but seriously there is a marginal difference between the measures
		//if you want to "improve" the rating removing the pow yielded me higher values
		//or via changing the example set making sets of participants that
		//don't overlap with any interests outside their clique/table
		//for every ordering of 3 different vertices
		/*for(int i=0;i<cnt;i++)
			for(int j=0;j<cnt;j++)
				for(int k=0;k<cnt;k++)
					if(i!=j&& i!=k && j!=k )
					{	
						//double value = Math.sqrt(edges[i][j] * edges[i][k]);
						double value = Math.min(edges[i][j], edges[i][k]);
						
						//The two neighbors on the same table? (nulls is no table)
						if(status.get(i).getTable()!= null && 
					    	status.get(i).getTable().equals(status.get(j).getTable()) && 
							status.get(i).getTable().equals(status.get(k).getTable()))
							clusteredSum += value;

						totalSum +=value;
					}
		*/
		
	/*	for (AID table: clusterSumPerTables.keySet()) {
			System.out.print("CK("+table.getLocalName()+"):"+ 
				round(clusterSumPerTables.get(table)/totalSumPerTables.get(table))+"\t");
		}
		System.out.println();*/
		
		if(totalSum > 0)
			return clusteredSum / totalSum;
		return -1;
		
	}
	

}
